from datetime import datetime
import json
from flask import Blueprint, request, url_for, jsonify, send_file, make_response
from webapp import db
from webapp.models import Pic, Album, Tag, Work, Setting, Volume, Actress, models_mapping
from webapp.const import RedisKey
from webapp.plugins import cache_utils as cache
from webapp.plugins.tasks import check_pics_task, create_thumbnail_task, delete_thumbnail_task, move_to_recycle_task, clear_cache
from webapp.plugins.image_apis import delete_image_file
from webapp.plugins.functions import search_, now, archive_albums_info, site_info, get_pic_context, BaseCache
from webapp.plugins.core import single_upload
from flask_login import login_required
from sqlalchemy.sql import desc, func
import zipfile
from io import BytesIO


api_blueprint = Blueprint(
    'api',
    __name__
)


@api_blueprint.route('/create', methods=['POST'])
@login_required
def create():
    form = request.json
    name_text = form.get('name')
    label = form.get('label')
    if not name_text:
        return ''
    names = name_text.split(',')
    success_created = []
    if label == 'album':
        for name in names:
            if not Album.query.filter_by(name=name).first():
                new_album = Album(name)
                db.session.add(new_album)
                success_created.append(name)
        db.session.commit()
        clear_cache.apply_async(label='album')
    elif label == 'tag':
        for name in names:
            if not Tag.query.filter_by(name=name).first():
                new_tag = Tag(name)
                db.session.add(new_tag)
                success_created.append(name)
        db.session.commit()
        clear_cache.apply_async(label='tag')
    elif label == 'volume':
        actress_id = form.get('actress_id')
        for name in names:
            if not Volume.query.filter_by(name=name, actress_id=actress_id).first():
                new_volume = Volume(name, actress_id)
                db.session.add(new_volume)
                success_created.append(name)
        db.session.commit()
        clear_cache.apply_async(label='volume')

    elif label == 'actress':
        for name in names:
            if not Actress.query.filter_by(name=name).first():
                new_actress = Actress(name)
                db.session.add(new_actress)
                success_created.append(name)
        db.session.commit()
        clear_cache.apply_async(label='actress')
    return json.dumps({'status': 1, 'info': f'{label}: {",".join(success_created)} 创建成功'})


@api_blueprint.route('/batch_join_albums', methods=['POST'])
@login_required
def batch_join_albums():
    """
    相册页面批量加入标签/相册/卷/模特
    :return:
    """
    try:
        data = request.json
        pics = set(Pic.query.filter(Pic.id.in_(data['pics'])).all())
        albums = Album.query.filter(Album.id.in_(data['albums'])).all() if data['albums'] else []
        tags = Tag.query.filter(Tag.id.in_(data['tags'])).all() if data['tags'] else []
        volume = Volume.query.get(data['volumes']) if data['volumes'] else None
        actresses = Actress.query.filter(Actress.id.in_(data['actresses'])).all() if data['actresses'] else []
        if albums:
            for album in albums:
                insert_pics = pics.difference(album.pics)
                album.pics.extend(insert_pics)
                BaseCache.pics_count_refresh('album', album.id, len(insert_pics))
        if tags:
            for tag in tags:
                insert_pics = pics.difference(tag.pics)
                tag.pics.extend(insert_pics)
                BaseCache.pics_count_refresh('tag', tag.id, len(insert_pics))
        if volume:
            insert_pics = pics.difference(volume.pics)
            volume.pics.extend(insert_pics)
            BaseCache.pics_count_refresh('volume', volume.id, len(insert_pics))
            volume.actress.pics.extend(pics.difference(volume.actress.pics))
            BaseCache.pics_count_refresh('actress', volume.actress.id, len(insert_pics))
        if actresses:
            for actress in actresses:
                insert_pics = pics.difference(actress.pics)
                actress.pics.extend(insert_pics)
                BaseCache.pics_count_refresh('actress', actress.id, len(insert_pics))
        db.session.commit()
        return json.dumps({'status': 1, 'info': '操作成功'})
    except Exception as e:
        return json.dumps({'status': 0, 'info': str(e)})


@api_blueprint.route('/pic_album_tag_update', methods=['POST'])
@login_required
def pic_album_tag_update():
    """
    picture页面更新相册/标签/卷/模特信息
    :return:
    """
    try:
        # 更新相册和标签信息
        data = request.json
        pic_info = set(data['data'])
        pic = Pic.query.get(data['pic_id'])
        new_albums = []
        new_tags = []
        new_volumes = []
        new_actresses = []

        # 初始化缓存
        # album_cache = AlbumCache()
        # tag_cache = TagCache()
        # volume_cache = VolumeCache()

        for resp in pic_info:
            label, label_name = resp.split('-', maxsplit=1)
            if label_name.endswith('(已存档)'):
                label_name = label_name[:-5]
            if label == 'album':
                new_albums.append(label_name)
                album = Album.query.filter_by(name=label_name).first()
                if album and album not in pic.albums:
                    pic.albums.append(album)
                elif not album:
                    album = Album(label_name)
                    album.pics.append(pic)
                # album_cache.update(
                #     {'id': album.id, 'name': album.name, 'rate': album.rate, 'pv': album.pv, 'count': album.amount})

            elif label == 'tag':
                new_tags.append(label_name)
                tag = Tag.query.filter_by(name=label_name).first()
                if tag and tag not in pic.tags:
                    pic.tags.append(tag)
                elif not tag:
                    tag = Tag(label_name)
                    tag.pics.append(pic)
                # tag_cache.update(
                #     {'id': tag.id, 'name': tag.name, 'pv': tag.pv, 'count': tag.amount})

            elif label == 'volume':
                new_volumes.append(int(label_name))
                volume = Volume.query.filter_by(id=label_name).first()
                if volume and volume not in pic.volumes:
                    pic.volumes.append(volume)
                    if volume.actress not in pic.actresses:
                        pic.actresses.append(volume.actress)
                        new_actresses.append(volume.actress.name)
                # volume_cache.update(
                #     {'id': volume.id, 'name': volume.name, 'rate': volume.rate, 'pv': volume.pv, 'count': volume.amount})

            elif label == 'actress':
                new_actresses.append(label_name)
                actress = Actress.query.filter_by(name=label_name).first()
                if actress and actress not in pic.actresses:
                    pic.actresses.append(actress)

        for album_name in set(album.name for album in pic.albums).difference(new_albums):
            pic.albums.remove(Album.query.filter_by(name=album_name).first())
        for tag_name in set(tag.name for tag in pic.tags).difference(new_tags):
            pic.tags.remove(Tag.query.filter_by(name=tag_name).first())
        for volume_id in set(volume.id for volume in pic.volumes).difference(new_volumes):
            pic.volumes.remove(Volume.query.filter_by(id=volume_id).first())
        for actress_name in set(actress.name for actress in pic.actresses).difference(new_actresses):
            pic.actresses.remove(Actress.query.filter_by(name=actress_name).first())

        db.session.commit()

        # 反馈新的相册和标签信息
        pic = Pic.query.get(data['pic_id'])

        return json.dumps({
            'status': 1,
            'pic_actresses': pic.actresses_html(blank=True),
            'pic_albums': pic.albums_html(blank=True),
            'pic_volumes': pic.volumes_html(blank=True),
            'pic_tags': pic.tags_html(blank=True),
        })
    except Exception as e:
        return json.dumps({'status': 0, 'info': str(e)})


@api_blueprint.route('/pic_rotate', methods=['GET'])
@login_required
def pic_rotate():
    """旋转图片180度"""
    pic_id = request.args.get('pic_id')
    pic = Pic.query.get(pic_id)

    if not pic.info:
        rotate = 0
    else:
        rotate = pic.info.get('rotate', 0)

    if rotate + 180 >= 360:
        rotate = 0
    else:
        rotate += 180
    pic.info_update({'rotate': rotate})
    return json.dumps({'status': 0, 'rotate': rotate})


@api_blueprint.route('/pic_scalex', methods=['GET'])
@login_required
def pic_scalex():
    """水平翻转图片"""
    pic_id = request.args.get('pic_id')
    pic = Pic.query.get(pic_id)
    if not pic.info:
        scalex = 1
    else:
        scalex = pic.info.get('scalex', 1)
    scalex = -scalex
    pic.info_update({'scalex': scalex})
    return json.dumps({'status': 0, 'scalex': scalex})


@api_blueprint.route('/delete')
@login_required
def delete():
    label = request.args.get('label')
    label_id = request.args.get('id')
    # 删除相册
    if label_id and label == 'album':
        try:
            album = Album.query.get(label_id)
            album.pics = []  # 把相册中的图片踢出
            db.session.delete(album)
            db.session.commit()
            return json.dumps({'status': 1, 'info': '相册"{}"已删除'.format(album.name)})

        except Exception as e:
            return json.dumps({'status': 0, 'info': str(e)})

    # 删除标签
    elif label_id and label == 'tag':
        try:
            tag = Tag.query.get(label_id)
            tag.pics = []  # 把标签中的图片踢出
            db.session.delete(tag)
            db.session.commit()
            return json.dumps({'status': 1, 'info': '相册"{}"已删除'.format(tag.name)})
        except Exception as e:
            return json.dumps({'status': 0, 'info': str(e)})

    # 删除卷
    elif label_id and label == 'volume':
        try:
            volume = Volume.query.get(label_id)
            volume.pics = []  # 把卷中的图片踢出
            db.session.delete(volume)
            db.session.commit()
            return json.dumps({'status': 1, 'info': '卷"{}"已删除'.format(volume.name)})
        except Exception as e:
            return json.dumps({'status': 0, 'info': str(e)})

    # 删除图片
    elif label_id and label == 'pic':

        pic = Pic.query.get(label_id)
        if not pic:
            return json.dumps({'status': 0, 'info': '该图片不存在'})

        pic.delete_time = datetime.utcnow()
        db.session.commit()
        return json.dumps({'status': 1, 'info': '图片已放入回收站'})
    else:
        return '操作错误'


@api_blueprint.route('/bulk_delete', methods=['POST'])
def bulk_delete():
    try:
        data = request.json
        pics = data.get('pics')
        now = datetime.utcnow()
        for pic_id in pics:
            pic = Pic.query.get(pic_id)
            pic.delete_time = now

        db.session.commit()
        return json.dumps({'status': 1, 'info': '图片已放入回收站'})
    except Exception as e:
        return json.dumps({'status': 0, 'info': str(e)})


@api_blueprint.route('/more_pic')
@login_required
def more_pic():
    page = request.args.get('page', type=int)
    source = request.args.get('source')
    source_id = request.args.get('source_id', type=int)
    load_all = 1 if request.args.get('all') else 0
    clear = request.args.get('clear', type=int)
    per_page_pics = request.args.get('limit', type=int, default=Setting.get('per_page_pics'))
    note__startswith = request.args.get('note')

    filter_options = []
    if note__startswith:
        filter_options.append(Pic.note.startswith(note__startswith))
    if not page:
        return ''
    if load_all and page != 1:
        return ''

    if source == 'home':
        pics = Pic.query.filter(Pic.delete_time==None).order_by(Pic.id.desc()).paginate(page=page, per_page=per_page_pics, error_out=False).items

    elif source == 'explore':
        if page > 1:
            return ''

        explore_filter_options = [Pic.delete_time==None]
        if request.args.get('unfiled'):
            explore_filter_options.extend([
                Pic.albums == None, Pic.actresses == None,
            ])
        elif request.args.get('album_id'):
            explore_filter_options.append(Pic.albums.any(Album.id == request.args.get('album_id', type=int)))
        elif request.args.get('actress_id'):
            explore_filter_options.append(Pic.actresses.any(Actress.id == request.args.get('actress_id', type=int)))
        elif request.args.get('volume_id'):
            explore_filter_options.append(Pic.volumes.any(Volume.id == request.args.get('volume_id', type=int)))
        elif request.args.get('tag_id'):
            explore_filter_options.append(Pic.tags.any(Tag.id == request.args.get('tag_id', type=int)))
        pics = Pic.query.filter(*explore_filter_options).order_by(func.random()).limit(per_page_pics)

    elif source == 'temp':
        if page > 1:
            return ''
        pic_info_hash = cache.hgetall(RedisKey.temp_pics_hash, content_type='json')
        pics = list(pic_info_hash.values())
        pics.sort(key=lambda x: x['file_name'])

    elif source == 'recycle':
        pics = Pic.query.filter(Pic.delete_time.isnot(None)).paginate(page=page, per_page=per_page_pics, error_out=False).items

    else:
        model = models_mapping.get(source)
        album_obj = model.query.get(source_id)

        if source == 'actress':
            volume_clear = 1 if request.args.get('volume_clear') else 0
            if volume_clear:
                # 排除已加入volume的图片
                volume_pics_id = []  # 存所有加入volume的pic_id
                for v in album_obj.volumes.all():
                    volume_pics_id.extend(v.pics_id)
                filter_options.append(~Pic.id.in_(volume_pics_id))

        pics = album_obj.pic_paginator(page,per_page_pics=per_page_pics, filter_options=filter_options, load_all=load_all).items

    if pics:
        pic_list = []
        for pic in pics:
            if source == 'temp':
                if pic['file_type'] == 'webp':
                    label_class = 'label-success'
                elif pic['file_type'] == 'png':
                    label_class = 'label-info'
                elif pic['file_type'] == 'jpg':
                    label_class = 'label-warning'
                elif pic['file_type'] == 'gif':
                    label_class = 'label-danger'
                else:
                    label_class = 'label-default'
                file_type_label = f'<span class="label {label_class} file_type">{pic["file_type"]}</span>'
                resp = '''<li id="{id}"><a href="{link}" title={file_name} target="_blank"><img src="{thumbnail_img}" alt="{file_name}"></a>{file_type_label}
                <input type="checkbox" class="pics_chk" name="pics_chk" value="{id}">
                </li>'''.format(
                    link=pic['image_url'],
                    thumbnail_img=pic['thumb_url'],
                    file_name=pic['file_name'],
                    file_type_label=file_type_label,
                    id=pic['file_hash']
                )
                pic_list.append(resp)
            elif not clear:
                resp = '''<li><a href="{link}">{thumbnail_img}</a>{file_type_label}
                <input type="checkbox" class="pics_chk" name="pics_chk" value="{id}">
                <div class="post-info">
                <div class="post-basic-info"><p>{note}</p><p>{actress}</p><p>{volume}</p><p>{album}</p><p>{tag}</p><p></div>
                <div class="post-info-rate">{rate}{pv}</div><div class="clear"> </div>
                </div></li>'''.format(
                    link=url_for('pic.one_pic', uid=pic.id, source=source, source_id=source_id),
                    thumbnail_img=pic.thumbnail_img,
                    file_type_label=pic.file_type_label,
                    note=pic.note_html(),
                    id=pic.id,
                    actress=pic.actresses_html(),
                    volume=pic.volumes_html(),
                    album=pic.albums_html(),
                    tag=pic.tags_html(),
                    rate=pic.rate_html(),
                    pv=pic.pv_html()
                )
                pic_list.append(resp)
            else:
                resp = '''<li><a href="{link}">{thumbnail_img}</a>{file_type_label}
                <input type="checkbox" class="pics_chk" name="pics_chk" value="{id}">
                </li>'''.format(
                    link=url_for('pic.one_pic', uid=pic.id, source=source, source_id=source_id),
                    thumbnail_img=pic.thumbnail_img,
                    file_type_label=pic.file_type_label,
                    id=pic.id
                )
                pic_list.append(resp)

        return json.dumps(pic_list)

    else:
        return ''


@api_blueprint.route('/more')
@login_required
def more():
    req = request.args.get('req')
    page = request.args.get('page', type=int)
    uid = request.args.get('id', 0, type=int)
    load_all = request.args.get('all', type=int)
    per_page_pics = request.args.get('limit', type=int, default=Setting.get('per_page_pics'))

    if not page or load_all:
        return ''

    if req in ('albums', 'volumes', 'actresses'):
        if req == 'albums':
            endpoint = 'pic.one_album'
            albums = Album.query.order_by(Album.id.desc()).paginate(page=page, per_page=per_page_pics, error_out=False).items
        elif req == 'actresses':
            endpoint = 'pic.one_actress'
            albums = Actress.query.order_by(Actress.id.desc()).paginate(page=page, per_page=per_page_pics, error_out=False).items
        else:
            endpoint = 'pic.one_volume'
            if uid:
                albums = Volume.query.filter(Volume.actress_id == uid).order_by(Volume.id.desc()).paginate(page=page, per_page=per_page_pics, error_out=False).items
            else:
                albums = Volume.query.order_by(Volume.id.desc()).paginate(page=page, per_page=per_page_pics, error_out=False).items
        if albums:
            albums_list = []
            for album in albums:
                resp = '''<li><a href="{url}">{cover}</a><div class="post-info"><div class="post-basic-info">
                <p>{name}</p><p>{create_time}</p>{volume_album}</div>
                <div class="post-info-rate">{rate}{volumes}{amount}{pv}</div>
                <div class="clear"> </div></div></li>'''.format(
                    url=url_for(endpoint, uid=album.id),
                    cover=album.cover,
                    name=album.name_html(),
                    create_time=album.create_time_html(),
                    volume_album='<p><i class="fa fa-newspaper-o"></i>&nbsp;&nbsp;<a href="{}">{}</a></p>'.format(url_for(endpoint, uid=album.actress.id), album.actress.name) if req == 'volumes' else '',
                    volumes='<i class="fa fa-th-large"></i>&nbsp;{}&nbsp;&nbsp;'.format(album.volume_amount) if req == 'actresses' else '',
                    rate=album.rate_html(),
                    amount=album.amount_html(),
                    pv=album.pv_html()
                )
                albums_list.append(resp)
            return json.dumps(albums_list)
        else:
            return ''

    elif req == 'tags':
        tags = Tag.query.order_by(Tag.id.desc()).paginate(page=page, per_page=per_page_pics, error_out=False).items
        if tags:
            tags_list = []
            for tag in tags:
                resp = '''<li><a href="{url}">{cover}</a><div class="post-info"><div class="post-basic-info">
                <p>{name}</p><p>{create_time}</p></div>
                <div class="post-info-rate">{amount}{pv}</div>
                <div class="clear"> </div></div></li>'''.format(
                    url=url_for('pic.one_tag', uid=tag.id),
                    cover=tag.cover,
                    name=tag.name_html(),
                    create_time=tag.create_time_html(),
                    amount=tag.amount_html(),
                    pv=tag.pv_html()
                )
                tags_list.append(resp)
            return json.dumps(tags_list)
        else:
            return ''

    elif req == 'search':
        keyword = request.args.get('key')
        result = search_(keyword)[(page-1) * per_page_pics: page * per_page_pics]
        if result:
            response = []
            for obj in result:
                resp = '''<li><a href="{url}">{img}</a><div class="post-info"><div class="post-basic-info">
                <p>{text}</p><p>{volume}</p><p>{album}</p><p>{tag}</p>{pic_chk}<p>{create_time}</p></div>
                <div class="post-info-rate">{rate}{amount}{pv}</div>
                <div class="clear"> </div></div></li>'''.format(
                    url=obj['url'],
                    img=obj['img'],
                    text=obj['text'],
                    volume=obj['volumes'],
                    album=obj['albums'],
                    tag=obj['tags'],
                    pic_chk='<input type="checkbox" class="pics_chk" name="pics_chk" value="{}">'.format(obj['id']) if obj['type'] == 'pic' else '',
                    create_time=obj['create_time'],
                    rate=obj['rate'],
                    amount=obj['amount'],
                    pv=obj['pv']
                )
                response.append(resp)

            return json.dumps(response)
        else:
            return ''

    else:
        return ''


@api_blueprint.route('/task')
@login_required
def task():
    task_name = request.args.get('task')
    msg = ''

    if task_name == 'check_task':
        check_pics_task.apply_async()
        # check_pics_task()

    elif task_name == 'create_thumbnail':
        create_thumbnail_task.apply_async()
        # create_thumbnail_task()

    elif task_name == 'delete_thumbnail':
        delete_thumbnail_task.apply_async()

    elif task_name == 'move_to_recycle':
        move_to_recycle_task.apply_async()

    return jsonify({'msg': msg})


@api_blueprint.route('/rate', methods=['POST', 'GET'])
@login_required
def rate():

    if request.method == 'GET':
        label = request.args.get('label')
        label_id = request.args.get('id')
        score = request.args.get('score', type=int)

    else:
        # request.method == 'POST'
        data = request.json
        label = data.get('label')
        label_id = data.get('id')
        score = data.get('score')

    try:
        if score in range(1, 6) and label == 'album':
            album = Album.query.get(label_id)
            album.new_rate(score)
            return jsonify({'status': 1, 'info': 'Album {}: {}'.format(label_id, score)})

        elif score in range(1, 6) and label == 'actress':
            actress = Actress.query.get(label_id)
            actress.new_rate(score)
            return jsonify({'status': 1, 'info': 'Actress {}: {}'.format(label_id, score)})

        elif score in range(1, 6) and label == 'volume':
            volume = Volume.query.get(label_id)
            volume.new_rate(score)
            return jsonify({'status': 1, 'info': 'Volume {}: {}'.format(label_id, score)})

        elif score in range(1, 6) and label == 'pic':
            pic = Pic.query.get(label_id)
            pic.new_rate(score)
            return jsonify({'status': 1, 'info': 'Pic {} : {}'.format(label_id, score)})

        else:
            return jsonify({'status': 0, 'info': '传入参数错误'})

    except Exception as e:
        return jsonify({'status': 0, 'info': str(e)})


@api_blueprint.route('/note', methods=['POST'])
@login_required
def note():
    try:
        data = request.json
        pic_id = data.get('id')
        text = data.get('note')
        Pic.query.filter_by(id=pic_id).update({'note': text})
        db.session.commit()
        return jsonify({'status': 1, 'info': 'success'})
    except Exception as e:
        return jsonify({'status': 0, 'info': str(e)})


@api_blueprint.route('/move_out_pic', methods=['POST'])
@login_required
def move_out_pic():
    try:
        data = request.json
        pics_id = data.get('pic')
        label = data.get('label')
        label_id = data.get('id')
        if label == 'album':
            obj = Album.query.get(label_id)
        elif label == 'tag':
            obj = Tag.query.get(label_id)
        elif label == 'volume':
            obj = Volume.query.get(label_id)
        elif label == 'actress':
            obj = Actress.query.get(label_id)
        else:
            obj = None

        if obj:
            count = 0
            for img in Pic.query.filter(Pic.id.in_(pics_id)).all():
                obj.pics.remove(img)
                count -= 1
            db.session.commit()
            BaseCache.pics_count_refresh(label, label_id, count)
        return jsonify({'status': 1, 'info': '图片已从"{}"中移出'.format(obj.name)})

    except Exception as e:
        return jsonify({'status': 0, 'info': str(e)})


@api_blueprint.route('/modify_album', methods=['POST'])
@login_required
def modify_album():
    data = request.json
    try:
        label = data.get('label')
        label_id = data.get('id')
        new_name = data.get('name')
        new_note = data.get('note')
        actress_id = data.get('actress_id')
        option_group = data.get('option_group')
        archived = data.get('archived')
        cancel_cover = data.get('cancel_cover')
        order_by = data.get('order_by')

        if label == 'album':
            obj = Album.query.filter_by(id=label_id).first()
        elif label == 'tag':
            obj = Tag.query.filter_by(id=label_id).first()
        elif label == 'volume':
            obj = Volume.query.filter_by(id=label_id).first()
            if actress_id:
                obj.actress_id = actress_id
        elif label == 'actress':
            obj = Actress.query.filter_by(id=label_id).first()
        else:
            return jsonify({'status': 1, 'info': 'success'})

        obj.name = new_name
        obj.update_pinyin(new_name)
        obj.note = new_note
        obj.update_meta('archived', archived)
        obj.update_meta('option_group', option_group)
        if order_by:
            obj.meta['order_by'] = order_by
        if cancel_cover:
            obj.cover_id = None

        db.session.commit()

        # 更新缓存
        BaseCache.common_update(
            label,
            label_id,
            {'name': obj.standard_name, 'pv': obj.pv, 'pinyin': obj.pinyin, 'meta': obj.meta})
        return jsonify({'status': 1, 'info': 'success'})

    except Exception as e:
        return jsonify({'status': 0, 'info': str(e)})


@api_blueprint.route('/set_cover')
@login_required
def set_cover():
    try:
        label = request.args.get('label')
        label_id = request.args.get('id')
        cover_id = request.args.get('cover')

        if label == 'album':
            Album.query.filter_by(id=label_id).update({'cover_id': cover_id})
        elif label == 'tag':
            Tag.query.filter_by(id=label_id).update({'cover_id': cover_id})
        elif label == 'volume':
            Volume.query.filter_by(id=label_id).update({'cover_id': cover_id})
        elif label == 'actress':
            Actress.query.filter_by(id=label_id).update({'cover_id': cover_id})
        else:
            pass
        db.session.commit()
        return jsonify({'status': 1, 'info': '封面设置成功'})
    except Exception as e:
        return jsonify({'status': 0, 'info': str(e)})


@api_blueprint.route('/count_temp')
@login_required
def count_temp():
    return jsonify(site_info.count_temp())


@api_blueprint.route('/count_recycle')
@login_required
def count_recycle():
    return jsonify(site_info.count_recycle())


@api_blueprint.route('/work_add', methods=['POST'])
@login_required
def work_add():
    status = 0
    msg = ''
    form = request.form
    try:
        if not Work.query.filter_by(title=form.get('work_title')).count():
            work = Work(
                form.get('work_title'),
                form.get('work_content'),
                form.get('work_priority', type=int))
            db.session.add(work)
            db.session.commit()
            status = 1
            msg += 'ok'
        else:
            work = Work('{}({})'.format(
                form.get('work_title'), now()),
                form.get('work_content'),
                form.get('work_priority', type=int))
            db.session.add(work)
            db.session.commit()
            status = 1
            msg += 'ok'
    except Exception as e:
        msg += str(e)

    return jsonify({'status': status, 'msg': msg})


@api_blueprint.route('/work_edit', methods=['POST'])
@login_required
def work_edit():
    form = request.form
    try:
        Work.query.filter_by(id=form.get('work_id')).update({'title': form.get('work_title'),
                                                             'content': form.get('work_content'),
                                                             'priority': form.get('work_priority')
                                                             })
        db.session.commit()
        return jsonify({'status': 1})
    except Exception as e:
        return jsonify({'status': 0, 'msg': str(e)})


@api_blueprint.route('/work_del')
@login_required
def work_del():
    page_id = request.args.get('id')
    try:
        page = Work.query.get(page_id)
        db.session.delete(page)
        db.session.commit()
        return jsonify({'status': 1})
    except Exception as e:
        return jsonify({'status': 0, 'msg': str(e)})


@api_blueprint.route('/import', methods=['POST'])
@login_required
def import_pics():
    """
    处理页面提交的导入请求，接收图片列表
    :return:
    """
    pics_data = request.json
    pic_hash_list = pics_data.get('pics')
    album_ids = pics_data.get('albums')
    tag_ids = pics_data.get('tags')
    volume_id = pics_data.get('volume')
    actress_ids = pics_data.get('actresses')
    for pic_hash in pic_hash_list:
        pic_info = cache.hget(RedisKey.temp_pics_hash, pic_hash, content_type='json')
        if not Pic.query.filter_by(file_hash=pic_info['file_hash']).first():
            pic = Pic(
                file_hash=pic_info['file_hash'],
                file_type=pic_info['file_type'],
                width=pic_info['width'],
                height=pic_info['height'],
                file_size=pic_info['file_size'],
                note=pic_info['file_name'],
            )
            db.session.add(pic)
        else:
            cache.hdel(RedisKey.temp_pics_hash, pic_hash)
            continue
        if tag_ids:
            tags = Tag.query.filter(Tag.id.in_(tag_ids)).all()
            pic.tags.extend(tags)
        if volume_id:
            volume = Volume.query.get(volume_id)
            pic.volumes.append(volume)
            pic.actresses.append(volume.actress)
        elif actress_ids:
            actresses = Actress.query.filter(Actress.id.in_(actress_ids)).all()
            pic.actresses.extend(actresses)
        if album_ids:
            albums = Album.query.filter(Album.id.in_(album_ids)).all()
            pic.albums.extend(albums)
        cache.hdel(RedisKey.temp_pics_hash, pic_hash)
    db.session.commit()
    return jsonify({'status': 1, 'info': '导入图片成功'})


@api_blueprint.route('/delete_temp_pics', methods=['POST'])
@login_required
def delete_temp_pic():
    try:
        data = request.json
        for pic_hash in data.get('pics'):
            pic_info = cache.hget(RedisKey.temp_pics_hash, pic_hash)
            # 删除图片
            delete_image_file(f'{pic_hash}.{pic_info["file_type"]}')
            cache.hdel(RedisKey.temp_pics_hash, pic_hash)
        return jsonify({'status': 1, 'info': '图片已删除'})
    except Exception as e:
        return jsonify({'status': 0, 'info': str(e)})


@api_blueprint.route('/recycle_restore', methods=['POST'])
@login_required
def recycle_restore():
    """从回收站恢复图片"""
    try:
        data = request.json
        for img in Pic.query.filter(Pic.id.in_(data.get('pics'))).all():
            img.delete_time = None
        db.session.commit()
        return json.dumps({'status': 1, 'info': '图片已从回收站恢复'})
    except Exception as e:
        return jsonify({'status': 0, 'info': str(e)})


@api_blueprint.route('/recycle_delete', methods=['POST'])
@login_required
def recycle_delete():
    """从回收站彻底删除"""
    try:
        data = request.json
        if data.get('all'):
            pics = Pic.query.filter(Pic.delete_time.isnot(None)).all()
        else:
            pics = Pic.query.filter(Pic.id.in_(data.get('pics'))).all()
        for pic in pics:
            pic.remove_image()
            db.session.delete(pic)
        db.session.commit()
        return json.dumps({'status': 1, 'info': '文件和数据库记录已删除'})
    except Exception as e:
        return jsonify({'status': 0, 'info': str(e)})


@api_blueprint.route('/archive_albums')
@login_required
def archive_albums():
    label = request.args.get('label')
    return archive_albums_info(label)


@api_blueprint.route('/setting_edit', methods=['POST'])
def setting_edit():
    label = request.args.get('label')
    if label == 'add':
        try:
            data = request.form
            new_setting = Setting(data.get('new_setting_label'), data.get('new_setting_desc'), data.get('new_setting_value'))
            db.session.add(new_setting)
            db.session.commit()
            return jsonify({'status': 1})
        except Exception as e:
            return jsonify({'status': 0, 'info': str(e)})

    elif label == 'edit':
        try:
            data = request.json
            setting = Setting.query.get(data.get('id'))
            setting.update(data.get('value'))
            return jsonify({'status': 1})
        except Exception as e:
            return jsonify({'status': 0, 'info': str(e)})


@api_blueprint.route('/upload', methods=['POST'])
def upload_api():
    form = request.form
    files = request.files.getlist('file')

    file_md5 = form.get('file_md5', '').lower()
    file_size = int(form.get('file_size'))
    return jsonify(single_upload(files, file_size, file_md5))


@api_blueprint.route('/temp_refresh', methods=['POST'])
def temp_refresh():
    page_files = request.json.get('pics')
    done = []  # 已经处理可以在页面上删除的图片
    for file_hash in page_files:
        if not cache.hget(RedisKey.temp_pics_hash, file_hash):
            done.append(file_hash)
    return jsonify({
        'amount': cache.hlen(RedisKey.temp_pics_hash),
        'done': done,
    })


@api_blueprint.route('/pic_context')
def pic_context():
    return jsonify(get_pic_context(request.args))


@api_blueprint.route('/cache_clear')
def cache_clear():
    clear_cache.apply_async()
    return jsonify({'status': 1})


@api_blueprint.route('/image_origin_url')
def image_origin_url():
    form = request.args
    source = form.get('resource', 'twitter')
    url = form.get('url')
    if source == 'twitter':
        origin_url = url.split('?')[0] + '.jpg:orig'
    else:
        origin_url = ''

    return jsonify({
        'status': 1,
        'origin_url': origin_url,
    })


@api_blueprint.route('/download')
def download_api():
    """打包下载图片"""
    form = request.args
    pics_id = form.get('pics', '').split(',')
    pics = Pic.query.filter(Pic.id.in_(pics_id)).all()

    if len(pics_id) != len(pics):
        return jsonify({
            'status': 0,
            'info': '部分图片不存在'
        }, )

    buffer = BytesIO()
    with zipfile.ZipFile(buffer, 'w', compression=zipfile.ZIP_DEFLATED) as zf:
        for pic in pics:
            zf.write(pic.full_path, arcname=f'{pic.note}.{pic.file_type}')

    buffer.seek(0)
    return send_file(buffer, as_attachment=True, download_name='pics_download.zip')


@api_blueprint.route('/load_filter')
def load_filter():
    volume_groups = {}
    for actress in site_info.all_actresses:
        if not actress['meta'].get('archived'):
            volume_groups[actress['id']] = [f'''<optgroup label="{actress['name']}" class="{actress['name']}">''']
    volume_data = BaseCache.select_options('volume', volume_groups)
    actress_data = BaseCache.select_options('actress')
    album_data = BaseCache.select_options('album')
    tag_data = BaseCache.select_options('tag')

    response = make_response(
        jsonify({
            'albums': album_data,
            'tags': tag_data,
            'actresses': actress_data,
            'volumes': volume_data,
        })
    )
    response.cache_control.max_age = 604800  # 7天
    return response


@api_blueprint.route('/all_categories')
def all_categories():
    response = make_response(
        jsonify({
            'albums': site_info.all_albums,
            'tags': site_info.all_tags,
            'actresses': site_info.all_actresses,
            'volumes': site_info.all_volumes,
        })
    )
    response.cache_control.max_age = 604800  # 7天
    return response
